﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using CodeCreator.CoreObj;
using iBing.Common.DbHelper.CoreObj;
using Common;
using CodeTemplate.DbHelper.CoreObj;
using iBing.Common.DbHelper;

namespace CodeCreator
{
    public class FileToReplace
    {
        private static Regex regForObj = new Regex("\\$\\$\\{Obj\\.((.|\r|\n)*?)\\}\\$\\$", RegexOptions.IgnoreCase | RegexOptions.Singleline);
        private static Regex regForCheck = new Regex("\\$\\$\\<((.|\r|\n)*?)\\>\\$\\$", RegexOptions.IgnoreCase | RegexOptions.Singleline);

        private static Regex regForRepeatSql = new Regex("##\\{Sqls((.|\r|\n)*?)\\}##", RegexOptions.IgnoreCase | RegexOptions.Singleline);
        private static Regex regForObjSql = new Regex("\\$\\$\\{Sql\\.((.|\r|\n)*?)\\}\\$\\$", RegexOptions.IgnoreCase | RegexOptions.Singleline);

        private static Regex regForRepeatJavaField = new Regex("##\\{JavaFields((.|\r|\n)*?)\\}##", RegexOptions.IgnoreCase | RegexOptions.Singleline);
        private static Regex regForObjJavaField = new Regex("\\$\\$\\{JavaField\\.((.|\r|\n)*?)\\}\\$\\$", RegexOptions.IgnoreCase | RegexOptions.Singleline);

        private static Regex regForRepeatDbField = new Regex("##\\{DbFields((.|\r|\n)*?)\\}##", RegexOptions.IgnoreCase | RegexOptions.Singleline);
        private static Regex regForObjDbField = new Regex("\\$\\$\\{DbField\\.((.|\r|\n)*?)\\}\\$\\$", RegexOptions.IgnoreCase | RegexOptions.Singleline);

        private static Regex regForRepeatJsField = new Regex("##\\{JsFields((.|\r|\n)*?)\\}##", RegexOptions.IgnoreCase | RegexOptions.Singleline);
        private static Regex regForObjJsField = new Regex("\\$\\$\\{JsField\\.((.|\r|\n)*?)\\}\\$\\$", RegexOptions.IgnoreCase | RegexOptions.Singleline);

        private static Regex regForRepeatCondition = new Regex("##\\{Conditions((.|\r|\n)*?)\\}##", RegexOptions.IgnoreCase | RegexOptions.Singleline);
        private static Regex regForObjCondition = new Regex("\\$\\$\\{Condition\\.((.|\r|\n)*?)\\}\\$\\$", RegexOptions.IgnoreCase | RegexOptions.Singleline);
              
                    

        /// <summary>
        /// 模板替换
        /// </summary>
        /// <param name="filePath"></param>
        public static void replaceFile(string filePath, Obj obj)
        {
            FileInfo fileInfo = new FileInfo(filePath);
            if (fileInfo.Exists)
            {
                //读取模板
                StreamReader fStream = new StreamReader(filePath, Encoding.UTF8);
                string str = fStream.ReadToEnd();
                fStream.Close();

                //处理Sql的重复项
                str = doRepeatObjs<ObjForSql>(str, obj, obj.Sqls, regForRepeatSql, regForObjSql);
                //处理JavaField的重复项
                str = doRepeatObjs<ObjJavaField>(str, obj, obj.JavaFields, regForRepeatJavaField, regForObjJavaField);
                //处理JavaField的重复项
                str = doRepeatObjs<ObjJsField>(str, obj, obj.JsFields, regForRepeatJsField, regForObjJsField);
                //处理JavaField的重复项
                str = doRepeatObjs<DbField>(str, obj, obj.DbFields, regForRepeatDbField, regForObjDbField);
                //处理JavaField的重复项
                str = doRepeatObjs<ObjForQuery>(str, obj, obj.Conditions, regForRepeatCondition, regForObjCondition);

                //处理判断
                //str = doCheckToObj<Obj>(obj, obj, str);
                //处理Obj后以的整体替换
                MatchCollection mObj = regForObj.Matches(str);
                foreach (Match m in mObj)
                {
                    object value_obj = ToolsReflect.GetValue<Obj>(obj, m.Groups[1].Value);
                    if (value_obj != null)
                    {
                        str = str.Replace(m.Groups[0].Value, value_obj.ToString());
                    }
                }

                //修改文件名
                string strFileName = fileInfo.Name;
                MatchCollection mFileName = regForObj.Matches(strFileName);
                foreach (Match m in mFileName)
                {
                    object value_obj = ToolsReflect.GetValue<Obj>(obj, m.Groups[1].Value);
                    if (value_obj != null)
                    {
                        strFileName = strFileName.Replace(m.Groups[0].Value, value_obj.ToString());
                    }
                }

                //保存文件
                StreamWriter sw = new StreamWriter(fileInfo.Directory + "\\" + strFileName);
                sw.Write(str);
                sw.Flush();
                sw.Close();

                if (strFileName == fileInfo.Name)
                {
                    //删除原文件
                    fileInfo.CopyTo(fileInfo.DirectoryName + "\\" + obj.JavaClassName + "_" + strFileName, true);
                }
            }
        }

        private static string doRepeatObjs<T>(string str, Obj obj, List<T> items, Regex regForRepeat, Regex regForObj)
        {
            MatchCollection mRepeatSql = regForRepeat.Matches(str);
            foreach (Match m in mRepeatSql)
            {
                string strOld = m.Groups[0].Value;
                string strNew = "";
                string strValue = m.Groups[1].Value;

                foreach (T os in items)
                {
                    string strItem = strValue;
                    //处理判断
                    strItem = doCheckToObj<T>(obj, os, strItem);

                    //替换属性值
                    MatchCollection mObjSql = regForObj.Matches(strItem);
                    foreach (Match mOS in mObjSql)
                    {
                        object value_obj = ToolsReflect.GetValue<T>(os, mOS.Groups[1].Value);
                        if (value_obj != null)
                        {
                            strItem = strItem.Replace(mOS.Groups[0].Value, value_obj.ToString());
                        }
                    }
                    strNew += strItem.TrimEnd() + "\r\n";
                }
                strNew = strNew.Trim();
                if (strNew.EndsWith(",\r\n"))
                    strNew = strNew.Substring(0, strNew.Length - 3) + "\r\n";
                else if (strNew.EndsWith(","))
                        strNew = strNew.Substring(0, strNew.Length - 1);
                str = str.Replace(strOld, strNew);
            }
            return str;
        }

        /// <summary>
        /// 处理判断模块
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="str"></param>
        /// <returns></returns>
        private static string doCheckToObj<T>(Obj obj,T objT, string str)
        {
            Regex regForCheck = new Regex("\\$\\$\\<((.|\r|\n)*?)\\>\\$\\$", RegexOptions.IgnoreCase | RegexOptions.Singleline);
            MatchCollection mCheck = regForCheck.Matches(str);
            if (mCheck.Count > 0)
            {
                foreach (Match m in mCheck)
                {
                    string strOld = m.Groups[0].Value;
                    string strNew = "";
                    string strValue = m.Groups[1].Value.Trim();
                    if (strValue.StartsWith("("))
                    {
                        string strCheck = strValue.Substring(strValue.IndexOf('(') + 1, strValue.IndexOf(')') - strValue.IndexOf('(') - 1);
                        //判断函数是否需要生成代码
                        if (CheckStringEqual<T>(obj, objT, strCheck))
                        {
                            strNew = strValue.Replace("(" + strCheck + ")", "");
                            strNew = ToolsFile.RemoveBeforeEnter(strNew);
                            str = ToolsFile.ReplaceAndRemoveAfterEnter(str, strOld, strNew);
                        }
                        else
                        {
                            //处理掉换行
                            strNew = "";
                            str = ToolsFile.ReplaceAndRemoveAfterEnter(str, strOld, strNew);
                        }
                    }
                }
            }
            return str;
        }

        /// <summary>
        /// 拆分判断公式，返回是否生成该断代码
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool CheckStringEqual<T>(Obj obj, T objT, string str)
        {
            str = str.Trim();

            if (str.IndexOf("!=") > 0)
            {
                str = str.Replace("!=", "!");
                string[] ss = str.Split('!');
                if (ss.Length == 2)
                {
                    if (CheckStringEqual<T>(obj,objT,ss[0],ss[1]))
                        return false;
                    else
                        return true;
                }
                else
                {
                    return false;
                }
            }
            else if (str.IndexOf('=') > 0)
            {
                string[] ss = str.Split('=');
                if (ss.Length == 2)
                {
                    if (CheckStringEqual<T>(obj, objT, ss[0], ss[1]))
                        return true;
                    else
                        return false;
                }
                else
                {
                    return false;
                }
            }
            else
                return false;
        }

        /// <summary>
        /// 判断两个Str是否相等
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="objT"></param>
        /// <param name="str1"></param>
        /// <param name="str2"></param>
        /// <returns></returns>
        public static bool CheckStringEqual<T>(Obj obj, T objT, string str1, string str2)
        {
            if (str1.StartsWith("Obj."))
            {
                str1 = str1.Substring(str1.IndexOf('.') + 1, str1.Length - str1.IndexOf('.') -1);
                str1 = ToolsReflect.GetValueToString<Obj>(obj, str1);
            }
            else
            {
                str1 = str1.Substring(str1.IndexOf('.') + 1, str1.Length - str1.IndexOf('.') - 1);
                str1 = ToolsReflect.GetValueToString<T>(objT, str1);
            }

            if (str2 == "")
            {
                if (str1 == ""||str1 == null)
                    return true;
                else
                    return false;
            }
            else
            {
                if (str1!= null && str2!= null && str1.ToUpper() == str2.ToUpper())
                    return true;
                else
                    return false;
            }
        }
    }
}
